package projetolp2.Sistem;

/**
 * 
 * Meal-Points - Projeto de Laborat�rio de programacao 2 - 2011.1
 * 
 * Sistema
 * 
 * @author Diego Tavares Felipe Travassos 
 * @author Felipe Travassos
 * @author Mayra Kelly
 *
 */

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;


public class Sistema {
	
	public static List<Estabelecimento> ranking = new ArrayList<Estabelecimento>();
	public static List<Estabelecimento> listaDeEstabelecimentos = new ArrayList<Estabelecimento>();
	public static List<Usuario> listaDeUsuarios = new ArrayList<Usuario>();
	public static List<Opiniao> listaDeOpinioes = new ArrayList<Opiniao>();
	
	static int  pos = 0;
	
	final static int NUMERO_ZERO = 0;
	
	/**
	 * Realiza a inicializacao do arquivo em sistema.
	 */

	public Sistema(){
		GerenciamentoDeArquivos.inicializaArquivos();
	}
	
	/**
	 * Realiza a mudança do nome do arquivo de estabelecimento.
	 * 
	 * @param caminho
	 *        O caminho do arquivo de estabelecimentos.
	 */
	public void mudaArqEst(String caminho){
		GerenciamentoDeArquivos.gravaCaminhoArq(caminho,"arquivos/sistema/caminhoArqEst.txt" );
	}
	
	/**
	 * Realiza a mudança do nome do arquivo de opinioes.
	 * 
	 * @param caminho
	 *        O caminho do arquivo de Opinioes.
	 */
	public void mudaArqOpi(String caminho){
		GerenciamentoDeArquivos.gravaCaminhoArq(caminho,"arquivos/sistema/caminhoArqOpi.txt" );
	}
	
    /**
     * Recupera uma lista de estabelecimentos de acordo com a quantidade de lugares passadas.
     * 
     * @param quantLugares
     *        A quantidade de estabelecimentos.
     * 
     * @return Uma Lista de estabelecimentos
     */
    public static List<Estabelecimento> recomendacao(int quantLugares){ 
		List<Estabelecimento> ranking = getRankingGeral();
		List<Estabelecimento> rankingFinal = new ArrayList<Estabelecimento>();
		for (int i = 0 ; i < quantLugares ; i++){
			rankingFinal.add(ranking.get(i));
		}
		return rankingFinal;
	}
    
    /**
     * Recupera uma lista de estabelecimentos de acordo com o tipo de estabelecimento escolhido.
     * 
     * @param tipo
     *       O tipo de estabelecimento.
     * 
     * @return Uma lista de estabelecimentos de acordo com o tipo do mesmo.
     */
    public static List<Estabelecimento> recomendacao(String tipoEstabelecimento, int quantidadeLugares){
    	List<Estabelecimento> ranking = getRankingGeral();
    	List<Estabelecimento> sugestao = new ArrayList<Estabelecimento>();
    	List<Estabelecimento> selecionados = new ArrayList<Estabelecimento>();
    	
        for (int i = 0 ; i < ranking.size() ; i++){
        	if(ranking.get(i).getNome().toLowerCase().contains(tipoEstabelecimento.toLowerCase())){
        		sugestao.add(ranking.get(i));
       		}
       	}
       	
        if(quantidadeLugares > sugestao.size()){
        	for(Estabelecimento estabelecimento : sugestao){
        		selecionados.add(estabelecimento);
        	}
        }else{
        	for(int i = 0; i < quantidadeLugares; i++){
        		selecionados.add(sugestao.get(i));
        	}
        }
        
        return selecionados;
	}
    
    /**
     * Realiza  recomendacao do sistema atraves do usuario e da quantidade de lugares.
     * 
     * @param nomeUsuario
     *        O nome do usuario do sistema.
     * @param quantEstabelecimento
     *        O numero de estabelecimentos.
     * @return
     *        A recomendacao por nome do usuario e numero dos estabelecimentos.
     * @throws Exception
     */
    public static List<Estabelecimento> recomendacaoPorUsuario(String nomeUsuario, int quantEstabelecimento) throws Exception{
    	List<Usuario> users = getListaUsuarios();
    	List<Estabelecimento> estabelecimentos = getListaEstabelecimentos();
    	Usuario usuario = null;
    	
    	for (Usuario user : users){
    		if (user.getNome().equals(nomeUsuario)){
    			usuario = user;
    		}
    	}
    	
    	int produtoEscalar =0, maiorProdutoEscalar =0;
    	List<Estabelecimento> listaAuxRec = new ArrayList<Estabelecimento>();
    	Usuario usuarioMaisSemelhante = new Usuario();
    	
    	for(int j =0; j<users.size(); j++){
    		for(int i= 0; i<estabelecimentos.size(); i++){
    			produtoEscalar+= usuario.getOpiniao().getVotos().get(i).getValorDeOpiniao()*users.get(j).getOpiniao().getVotos().get(i).getValorDeOpiniao();		
    		}
    		if(produtoEscalar > maiorProdutoEscalar){
 			   
				maiorProdutoEscalar = produtoEscalar;
				usuarioMaisSemelhante = users.get(j);
			}
    		produtoEscalar = 0;
    	}
    	
    	for(int i =0; i <estabelecimentos.size(); i++){
    		if(usuario.getOpiniao().getVotos().get(i).getValorDeOpiniao()!= NUMERO_ZERO &&
    				usuarioMaisSemelhante.getOpiniao().getVotos().get(i).getValorDeOpiniao()>NUMERO_ZERO){
    			listaAuxRec.add(estabelecimentos.get(i));
    		}
    	}
    	
    	for (int i = 0; i< listaAuxRec.size(); i++){
    		for (int j = 1; j< listaAuxRec.size()-i; j++){
    			if(listaAuxRec.get(j).compareTo(listaAuxRec.get(j-1)) > 0){
    				Collections.swap(listaAuxRec, j, j-1);
    			}
    		}
    	}
    	
    	return listaAuxRec;
    } 
    /**
     * Retorna uma lista de estabelecimentos de acordo com a localizacao escolhida
     * 
     * @param localizacao
     * Um bairro, rua ou numero que sera verificado
     * @param quantidadeLugares
     * A quantidade de estabelecimentos que sera recomendada ao usuario
     * @return
     * A lista de estabelecimentos recomendados
     */
    public static List<Estabelecimento> recomendacaoPorLocalizacao(String localizacao, int quantidadeLugares){
    	List<Estabelecimento> ranking = getRankingGeral();
    	List<Estabelecimento> sugestao = new ArrayList<Estabelecimento>();
    	List<Estabelecimento> selecionados = new ArrayList<Estabelecimento>();
    	
        for (int i = 0 ; i < ranking.size() ; i++){
        	if(ranking.get(i).getEndereco().toLowerCase().contains(localizacao.toLowerCase())){
        		sugestao.add(ranking.get(i));
       		} 
       	}
       	
        if(quantidadeLugares > sugestao.size()){
        	for(Estabelecimento estabelecimento : sugestao){
        		selecionados.add(estabelecimento);
        	}
        }else{
        	for(int i = 0; i < quantidadeLugares; i++){
        		selecionados.add(sugestao.get(i));
        	}
        }
        
        return selecionados;
	}
    
    /**
     * Realiza a recomendacao do sistema atraves do tipo de almoco e a quantidade de lugares.
     * 
     * @param tipoDeAlmoco
     *        O tipo de almoco do estabelecimento.
     * @param quantidadeLugares
     *        A quantidade de estabelecimentos.
     * @return
     *        A recomendacao atraves do tipo de almoco e do numero de estabelecimentos.
     */
    
    public static List<Estabelecimento> recomendacaoAlmoco(String tipoDeAlmoco, int quantidadeLugares){
    	List<Estabelecimento> ranking = getRankingGeral();
    	List<Estabelecimento> sugestao = new ArrayList<Estabelecimento>();
    	List<Estabelecimento> selecionados = new ArrayList<Estabelecimento>();
    	
        for (int i = 0 ; i < ranking.size() ; i++){
        	if(ranking.get(i).getTipoAlmoco().getNovaCategoria().toLowerCase().equals(tipoDeAlmoco.toLowerCase())){
        		sugestao.add(ranking.get(i));
       		}
       	}
       	
        if(quantidadeLugares > sugestao.size()){
        	for(Estabelecimento estabelecimento : sugestao){
        		selecionados.add(estabelecimento);
        	}
        }else{
        	for(int i = 0; i < quantidadeLugares; i++){
        		selecionados.add(sugestao.get(i));
        	}
        }
        
        return selecionados;
    }
    
    /**
     * Recupera uma lista de estabelecimentos de acordo com os gostos do usuario em relacao aos estabelecimentos.
     * 
     * @param usuario
     *        O usuario do sistema.
     * 
     * @return Uma lista de estabelecimentos mais "parecidos" com o usuario.
     */
    public static List<Estabelecimento> recomendacao(String nomeUsuario){
    	List<Usuario> users = getListaUsuarios();
    	List<Estabelecimento> estabelecimentos = getListaEstabelecimentos();
    	Usuario usuario = null;
    	
    	for (Usuario user : users){
    		if (user.getNome().equals(nomeUsuario)){
    			usuario = user;
    		}
    	}
    	
    	int produtoEscalar =0, maiorProdutoEscalar =0;
    	List<Estabelecimento> listaAuxRec = new ArrayList<Estabelecimento>();
    	Usuario usuarioMaisSemelhante = new Usuario();
    	
    	for(int j =0; j<users.size(); j++){
    		for(int i= 0; i<estabelecimentos.size(); i++){
    			produtoEscalar+= usuario.getOpiniao().getVotos().get(i).getValorDeOpiniao()*users.get(j).getOpiniao().getVotos().get(i).getValorDeOpiniao();
    			if(produtoEscalar > maiorProdutoEscalar){
    			   
    				maiorProdutoEscalar = produtoEscalar;
    				usuarioMaisSemelhante = users.get(j);
    			}	
    		}
    	}
    	for(int i =0; i <estabelecimentos.size(); i++){
    		if(usuario.getOpiniao().getVotos().get(i).getValorDeOpiniao()== NUMERO_ZERO &&
    				usuarioMaisSemelhante.getOpiniao().getVotos().get(i).getValorDeOpiniao()>NUMERO_ZERO){
    			listaAuxRec.add(estabelecimentos.get(i));
    		}
    	}
    	return listaAuxRec; 
    }
    
    /**
     * Adiciona estabelecimentos na lista de Estabelecimentos.
     * 
     * @param estabelecimento
     *        O estabelecimento escolhido.
     */
    public static void adicionaEstabelecimento(Estabelecimento estabelecimento){
    	estabelecimento.setPosicao(pos);
    	listaDeEstabelecimentos.add(estabelecimento);
    	pos++;
    }
    
    /**
     * Realiza a conversao da lista de estabelecimentos para String.
     * 
     * @param estabelecimentos
     *        Uma lista de estabelecimentos do sistema.
     * @return
     *       A lista transformada em lista de String.
     */
    
	public static List<String> converteEstabelecimentos(List<Estabelecimento> estabelecimentos){
    	List<String> saida = new ArrayList<String>();
    	
    	for(Estabelecimento estabelecimento : estabelecimentos){
    		saida.add(estabelecimento.getNome() + " - " + estabelecimento.getEndereco());
    	}
    	return saida;
	}	
	
	
    /**
     * Realiza a conversao da lista de opinioes para String.
     * 
     * @param opinioesString
     * recebe um array de Strings com valores de opinioes
     * @return
     * um array do tipo OpinioesDeUsuarios para poder realizar o cadastramento do usuario posteriormente
     */
    public static List<OpinioesDeUsuarios> converteOpinioes(List<String> opinioesString){
    	List<OpinioesDeUsuarios> opinioesConvertidas = new ArrayList<OpinioesDeUsuarios>();
    	for (String opiniao : opinioesString){
    		if (opiniao.startsWith("-5")){
    			opinioesConvertidas.add(OpinioesDeUsuarios.DETESTO);
    		}
    		else if (opiniao.startsWith("-4")){
    			opinioesConvertidas.add(OpinioesDeUsuarios.MUITO_RUIM);
    		}
    		else if (opiniao.startsWith("-3")){
    			opinioesConvertidas.add(OpinioesDeUsuarios.BASTANTE_RUIM);
    		}
    		else if (opiniao.startsWith("-2")){
    			opinioesConvertidas.add(OpinioesDeUsuarios.RUIM);
    		}
    		else if (opiniao.startsWith("-1")){
    			opinioesConvertidas.add(OpinioesDeUsuarios.UM_POUCO_RUIM);
    		}
    		else if (opiniao.startsWith("0")){
    			opinioesConvertidas.add(OpinioesDeUsuarios.NAO_CONHECO);
    		}
    		else if (opiniao.startsWith("1")){
    			opinioesConvertidas.add(OpinioesDeUsuarios.NAO_EH_RUIM);
    		}
    		else if (opiniao.startsWith("2")){
    			opinioesConvertidas.add(OpinioesDeUsuarios.BONZINHO);
    		}
    		else if (opiniao.startsWith("3")){
    			opinioesConvertidas.add(OpinioesDeUsuarios.BASTANTE_BOM);
    		}
    		else if (opiniao.startsWith("4")){
    			opinioesConvertidas.add(OpinioesDeUsuarios.MUITO_BOM);
    		}
    		else if (opiniao.startsWith("5")){
    			opinioesConvertidas.add(OpinioesDeUsuarios.INCRIVEL);
    		}
    		else{
    			opinioesConvertidas.add(OpinioesDeUsuarios.NAO_CONHECO);
    		}
    	}return opinioesConvertidas;
    }
    
	private static void cadastraUsuario(Usuario usuario) throws Exception{ //modifiquei o metodo para estatico pra poder chamar no metodo abaixo
		if (listaDeUsuarios.contains(usuario)){
			throw new Exception("Usuario ja eh cadastrado");
		}
		listaDeUsuarios.add(usuario);

	}
	
	 /**
     * Cadastra um novo usuario no sistema
     * @param nomeUsuario
     * o nome do usuario a ser cadastrado (que devera ser unico para cada um)
     * @param listaDeOpinioes
     * as opinioes do usuario acerca de todos os estabelecimentos cadastrados no sistema.
     */
    public static void cadastraUsuario(String nomeUsuario, List<String> listaDeOpinioes) throws Exception{
        List<OpinioesDeUsuarios> votos = converteOpinioes(listaDeOpinioes);
        String dataHora = Sistema.horaDoSistema(); 
        Opiniao opiniao = new Opiniao(dataHora, nomeUsuario, votos);
        Usuario usuario = new Usuario(nomeUsuario, opiniao);
        
        cadastraUsuario(usuario);
        escreveUsuario(dataHora, nomeUsuario, listaDeOpinioes);
    }

	/**
	 * Lista a data e a hora, o nome do opinador e os votos dele sobre todos os restaurantes cadastrados
	 * @throws Exception
	 */
	public static void criaListaDeOpinioes() throws Exception{
		
		List<Opiniao>listaDasOpinioes = new ArrayList<Opiniao>();
		String[] arquivo = GerenciamentoDeArquivos.lerArquivo(GerenciamentoDeArquivos.getNomeArquivoUsuarios()).split("\n");
		for (String linha : arquivo){
			String[] opiniaoUsuario = linha.split(";");
			List<OpinioesDeUsuarios> listaVotos = new ArrayList<OpinioesDeUsuarios>(); 
		
			//recebendo os votos do usuario
			for(int i= 2; i < opiniaoUsuario.length; i++){
				if (opiniaoUsuario[i].replace(" ","").startsWith("-5:")){
					listaVotos.add(OpinioesDeUsuarios.DETESTO);
				}
				else if (opiniaoUsuario[i].replace(" ","").startsWith("-4:")){
					listaVotos.add(OpinioesDeUsuarios.MUITO_RUIM);
				}
				else if (opiniaoUsuario[i].replace(" ","").startsWith("-3:")){
					listaVotos.add(OpinioesDeUsuarios.BASTANTE_RUIM);
				}
				else if (opiniaoUsuario[i].replace(" ","").startsWith("-2:")){
					listaVotos.add(OpinioesDeUsuarios.RUIM);
				}
				else if (opiniaoUsuario[i].replace(" ","").startsWith("-1:")){
					listaVotos.add(OpinioesDeUsuarios.UM_POUCO_RUIM);
				}
				else if (opiniaoUsuario[i].replace(" ","").startsWith("0:")){
					listaVotos.add(OpinioesDeUsuarios.NAO_CONHECO);
				}
				else if (opiniaoUsuario[i].replace(" ","").startsWith("1:")){
					listaVotos.add(OpinioesDeUsuarios.NAO_EH_RUIM);
				}
				else if (opiniaoUsuario[i].replace(" ","").startsWith("2:")){
					listaVotos.add(OpinioesDeUsuarios.BONZINHO);
				}
				else if (opiniaoUsuario[i].replace(" ","").startsWith("3:")){
					listaVotos.add(OpinioesDeUsuarios.BASTANTE_BOM);
				}
				else if (opiniaoUsuario[i].replace(" ","").startsWith("4:")){
					listaVotos.add(OpinioesDeUsuarios.MUITO_BOM);
				}
				else if (opiniaoUsuario[i].replace(" ","").startsWith("5:")){
					listaVotos.add(OpinioesDeUsuarios.INCRIVEL);
				}else{
					listaVotos.add(OpinioesDeUsuarios.NAO_CONHECO);
				}
			}
			Opiniao armazenaOpiniao = new Opiniao(opiniaoUsuario[0], opiniaoUsuario[1], listaVotos); 
			listaDasOpinioes.add(armazenaOpiniao);
		}
		listaDeOpinioes =  listaDasOpinioes;
	}
	
	/**
	 * Recupera a lista de opinioes do sistema.
	 * 
	 * @return
	 *        A lista de opinioes do sistema.
	 */
	
	public static List<Opiniao> getListaDeOpinioes(){
		return listaDeOpinioes;
	}


	/**
	 * Lista todos os estabelecimentos cadastrados no arquivo.
	 * 
	 * @throws Exception 
	 * 
	 */
	public static void criaListaEstabelecimentos()throws Exception {
		String arquivo = GerenciamentoDeArquivos.getNomeArquivoEstabelecimentos();
		String dados = GerenciamentoDeArquivos.lerArquivo(arquivo);
		String endereco, almocoArquivo;
		String[] linhasArquivo = dados.split("\n");
		String[] dadosEstabelecimentos;
		TipoDeAlmoco tipoAlmoco;
		Estabelecimento estabelecimentoCorrente;
		TipoDeEstabelecimento tipoEstabelecimento = TipoDeEstabelecimento.RESTAURANTE; //verificar o tipo do restaurante quando ler do arquivo
		List<Estabelecimento> listaEstabelecimentos = new ArrayList<Estabelecimento>();
		
		for (String linha : linhasArquivo){
			//armazenando objetos do tipo Estabelecimento com os parametros lidos no arquivo
			dadosEstabelecimentos = linha.split(";");
			
			endereco = dadosEstabelecimentos[1];
			almocoArquivo = dadosEstabelecimentos[2];
			if (almocoArquivo.equals(" A la carte")){
				tipoAlmoco = TipoDeAlmoco.A_LACARTE;
			}else if (almocoArquivo.equals(" Prato feito")){
				tipoAlmoco = TipoDeAlmoco.PRATO_FEITO;
			}else if (almocoArquivo.equals(" Self-service")){
				tipoAlmoco = TipoDeAlmoco.SELF_SERVICE;
			}else{
				throw new Exception("Tipo de almoco nao encontrado");
			}

			estabelecimentoCorrente = new Estabelecimento(dadosEstabelecimentos[0], endereco, tipoAlmoco, tipoEstabelecimento, 0); 
			listaEstabelecimentos.add(estabelecimentoCorrente);
		}
		listaDeEstabelecimentos =  listaEstabelecimentos;
	}
	
	/**
	 * Recupera a lista de estabelecimentos do sistema.
	 * 
	 * @return
	 *        A lista de estabelecimentos do sistema.
	 */
	
	public static List<Estabelecimento> getListaEstabelecimentos(){
		return listaDeEstabelecimentos;
	}
	
	/**
	 * Lista todos os usuarios do arquivo
	 * @throws Exception
	 */
	public static void criaListaUsuarios()throws Exception {
		List<Opiniao> opinioesArquivo = new ArrayList<Opiniao>(); 
		List<Usuario> listaUsuarios = new ArrayList<Usuario>(); 
		
		opinioesArquivo = getListaDeOpinioes();
		String nome = "";
		Usuario usuarioCorrente;
		int usuariosSemNome = 1;
		for (Opiniao o : opinioesArquivo){
			nome = o.getNomeUsuario();
			if (nome.replace(" ", "").equals("")){
				nome = "Sem Nome Cadastrado " + usuariosSemNome;
				usuariosSemNome++;
			}
			usuarioCorrente = new Usuario(nome, o); 
			listaUsuarios.add(usuarioCorrente);
		}
		listaDeUsuarios =  listaUsuarios;
	}
	
	/**
	 * Recupera a lista de usuarios do sistema.
	 * 
	 * @return
	 *       A lista de usuarios do sistema.
	 */
	
	public static List<Usuario> getListaUsuarios(){
		return listaDeUsuarios;
	}
	
	/**
	 * Realiza a atualizacao das listas de opinioes, estabelecimentos de usuarios e a do ranking.
	 * 
	 * @throws Exception
	 */
	public static void atualizaListas() throws Exception{
		try{
			criaListaDeOpinioes();			
		}catch(Exception e){
			System.err.println("CriaListaOpinioes");
		}
		try{
			criaListaEstabelecimentos();	
		}catch(Exception e){
			System.err.println(e.getMessage());
		}
		try{
			criaListaUsuarios();	
		}catch(Exception e){
			System.err.println(e.getMessage());
		}
		try{
			criaRankingGeral();	
		}catch(Exception e){
			System.err.println(e.getMessage());
		}
	}

	/**
	 * Lista o nome de todos os usuarios cadastrados
	 * @return
	 * um array com o nome dos usuarios do sistema
	 * @throws Exception
	 */
	public static List<String> nomeDeUsuarios() throws Exception{
		List<Usuario> usuariosArquivo = getListaUsuarios();
		List<String> nomeUsuarios =new ArrayList<String>();
		String nomeUsuario= "";
		int usuariosSemNome = 1;
		
		for (Usuario usuario : usuariosArquivo){
			nomeUsuario = usuario.getNome();
			if (nomeUsuario.replace(" ", "").equals("")){
				nomeUsuarios.add("Sem Nome Cadastrado " + usuariosSemNome);
			}else{
				nomeUsuarios.add(nomeUsuario);
			}
		}
		
		return nomeUsuarios;
	}
	
	/**
	 * Lista o nome de todos os estabelecimentos cadastrados
	 * @return
	 * um array com o nome dos usuarios
	 * @throws Exception
	 */
	public static List<String> nomeDeEstabelecimentos() throws Exception{
		List<Estabelecimento> estabelecimentosArquivo = getListaEstabelecimentos();
		List<String> nomeEstabelecimentos = new ArrayList<String>();
		
		for (Estabelecimento est : estabelecimentosArquivo){
			nomeEstabelecimentos.add(est.getNome());
		}
		return nomeEstabelecimentos;
	}
	
	/**
	 * Recupera o numero de estabelecimentos do sistema.
	 * 
	 * @return
	 * A quantidade de esabelecimentos cadastrados no arquivo
	 * @throws Exception
	 */
	public static int quantidadeDeEstabelecimentos() throws Exception{
		return getListaEstabelecimentos().size();
	}

	
	/**
	 * Armazena a opiniao do usuario atraves do nome do mesmo.
	 * 
	 * @param nomeUsuario
	 * O nome do usuario do qual se deseja saber a opiniao 
	 * @return
	 * Um arra com todas as opinioes desse usuario
	 * @throws Exception
	 */
	public static List<OpinioesDeUsuarios> OpiniaoUsuario(String nomeUsuario) throws Exception{
		List<Opiniao> todasOpinioes = getListaDeOpinioes();
		List<Usuario> usuarios = getListaUsuarios();
		int numero = 0;
		for (int i = 0; i<usuarios.size();i++){
			if (usuarios.get(i).getNome().equals(nomeUsuario)) numero = i;
		}
		return todasOpinioes.get(numero).getVotos();
	}
	
	/**
	 * Armazena a opiniao de usuario atraves do nome do mesmo e do nome do estabelecimento.
	 * 
	 * @param nomeUsuario
	 *        O nome do usuario do sistema.
	 * @param nomeEstabelecimento
	 *        O nome do estabelecimento.
	 * @return
	 *        A opiniao do usuario sobre o estabelecimento passado.
	 * @throws Exception
	 */
	
	public static String OpiniaoUsuario(String nomeUsuario, String nomeEstabelecimento) throws Exception{
		List<Usuario> usuarios = getListaUsuarios();
		int posicaoEst = posicaoEstabelecimento(nomeEstabelecimento);
		
		for (int i = 0; i<usuarios.size();i++){
			if (usuarios.get(i).getNome().equals(nomeUsuario)){
				return "" + usuarios.get(i).getOpiniao().getVotos().get(posicaoEst).getNomeDaOpiniao();
			}
		}
		return "nada foi encontrado";
	}
	
	/**
	 * Recupera o ranking dos estabelecimentos no formato de String.
	 * 
	 * @return
	 *        O ranking dos estabelecimentos.
	 */
	
	public static String rankingGeralString(){
		String saida = "";
		try{
		List<Estabelecimento> ranking = getRankingGeral(); 
		

		for(Estabelecimento est : ranking){
			saida += est.getPopularidade() + " - " + est.getNome() + ";";
		}
		}catch(Exception e){
			System.err.println(e.getMessage());
		}
		return saida;	}
	
	/**
	 * Recupera a popularidade do estabelecimento.
	 * 
	 * @param nomeEstabelecimento
	 *        O nome do estabelecimento.
	 * @return
	 *        A popularidade do estabelecimento.
	 * @throws Exception
	 */

	
	public static int getPop(String nomeEstabelecimento) throws Exception{
		List<Usuario> users = getListaUsuarios();
		int posicao = posicaoEstabelecimento(nomeEstabelecimento);
		int cont = 0;
		for (int i = 0; i< users.size() ; i++){
			cont += users.get(i).getOpiniao().getVotos().get(posicao).getValorDeOpiniao();
		}
		return cont;
	}
	
	/**
	 * Realiza a criacao do ranking de estabelecimentos.
	 * 
	 * @throws Exception
	 */
	

    public static void criaRankingGeral() throws Exception{
    	List<Estabelecimento> todosEstabelecimentos = getListaEstabelecimentos();
    	List<Integer> popularidades = new ArrayList<Integer>();
    	
    	List<Estabelecimento> ordenados = new ArrayList<Estabelecimento>();
    	
    	for (Estabelecimento estabelecimento : todosEstabelecimentos){
    		popularidades.add(estabelecimento.getPopularidade());
    	}
    	
    	Collections.sort(popularidades);
    	int i = 38;
		while(ordenados.size() < 39){
			for (int j = 0; j < todosEstabelecimentos.size(); j++){
    			if (todosEstabelecimentos.get(j).getPopularidade() == popularidades.get(i)){
        			ordenados.add(todosEstabelecimentos.get(j));
        			if(i > 0)
        				i--;
    			}
			}
    	}
		ranking =  ordenados;
	}
    
    /**
     * Recupera o ranking dos estabelecimentos.
     * 
     * @return
     *        O ranking dos estabelecimentos.
     */
    
    public static List<Estabelecimento> getRankingGeral(){
    	return ranking;
    }
    
    /**
     * Recupera a posicao do estabelecimento na lista.
     * 
     * @param nomeEstabelecimento
     *        O nome do estabelecimento.
     * @return
     *        A posicao do estabelecimento na lista.
     * @throws Exception
     */
	
	public static int posicaoEstabelecimento(String nomeEstabelecimento) throws Exception{
		List<Estabelecimento> listaEst = getListaEstabelecimentos();
		int numeroDefault = 0;
		for (int i = 0; i < listaEst.size(); i++){
			if (listaEst.get(i).getNome().equals(nomeEstabelecimento)){
				return i;
			}
		}
		return numeroDefault;
	}
	
	/**
	 * Realiza a escritura da opiniao do usuario no arquivo.
	 * 
	 * @param dataHora
	 *        A data e hora da opiniao.
	 * @param nomeUsuario
	 *        O nome do usuario que opinou.
	 * @param opinioes
	 * 
	 */
	

	 
    public static void escreveUsuario(String dataHora, String nomeUsuario, List<String> opinioes){
        String texto = dataHora + ";" + nomeUsuario + ";";
        List<OpinioesDeUsuarios> listaOpinioes = converteOpinioes(opinioes);
        
        for (OpinioesDeUsuarios valor : listaOpinioes){
            if (valor == OpinioesDeUsuarios.DETESTO){
                texto+= OpinioesDeUsuarios.DETESTO.getNomeDaOpiniao() + ";";
                
            }else if (valor == OpinioesDeUsuarios.MUITO_RUIM){
                texto+= OpinioesDeUsuarios.MUITO_RUIM.getNomeDaOpiniao() + ";";
                
            }else if (valor == OpinioesDeUsuarios.BASTANTE_RUIM){
                texto+= OpinioesDeUsuarios.BASTANTE_RUIM.getNomeDaOpiniao() + ";";
                
            }else if (valor == OpinioesDeUsuarios.RUIM){
                texto+= OpinioesDeUsuarios.RUIM.getNomeDaOpiniao() + ";";
                
            }else if (valor == OpinioesDeUsuarios.UM_POUCO_RUIM){
                texto+= OpinioesDeUsuarios.UM_POUCO_RUIM.getNomeDaOpiniao() + ";";
                
            }else if (valor == OpinioesDeUsuarios.NAO_CONHECO){
                texto+= OpinioesDeUsuarios.NAO_CONHECO.getNomeDaOpiniao() + ";";
                
            }else if (valor == OpinioesDeUsuarios.NAO_EH_RUIM){
                texto+= OpinioesDeUsuarios.NAO_EH_RUIM.getNomeDaOpiniao() + ";";
                
            }else if (valor == OpinioesDeUsuarios.BONZINHO){
                texto+= OpinioesDeUsuarios.BONZINHO.getNomeDaOpiniao() + ";";
                
            }else if (valor == OpinioesDeUsuarios.BASTANTE_BOM){
                texto+= OpinioesDeUsuarios.BASTANTE_BOM.getNomeDaOpiniao() + ";";
                
            }else if (valor == OpinioesDeUsuarios.MUITO_BOM){
                texto+= OpinioesDeUsuarios.MUITO_BOM.getNomeDaOpiniao() + ";";
                
            }else if (valor == OpinioesDeUsuarios.INCRIVEL){
                texto+= OpinioesDeUsuarios.INCRIVEL.getNomeDaOpiniao() + ";";
                
            }else{
                texto+= OpinioesDeUsuarios.NAO_CONHECO.getNomeDaOpiniao() + ";";
            }
        }
        GerenciamentoDeArquivos.escreveArquivo("\n" + texto.substring(0,texto.lastIndexOf(";")), GerenciamentoDeArquivos.getNomeArquivoUsuarios(), true);
    }
    


    /**
     * Retorna a data e hora do Sistema
     * @return
     * A data e a hora (no formato DD/MM/AAAA HH:MM:SS)
     * 
     */
    public static String horaDoSistema(){
        System.currentTimeMillis();
        SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy hh:mm:ss");  
        return(sdf.format(new Date()));  
    }
    public List<Estabelecimento> recomendacaoUsuarioAlmoco(String nomeUsuario, int quantEstabelecimento, String TipoAlmoco) throws Exception{
    	List<Estabelecimento> sugestao = recomendacaoPorUsuario(nomeUsuario, quantEstabelecimento);
    	List<Estabelecimento> recomendacaoFinal = new ArrayList<Estabelecimento>();
    	
    	for (Estabelecimento estabelecimento : sugestao){
    		if (estabelecimento.getTipoAlmoco().getNovaCategoria().toLowerCase().contains(TipoAlmoco.toLowerCase())){
    			recomendacaoFinal.add(estabelecimento);
    		}
    	}
    	return recomendacaoFinal;
    }
    /**
     * Recomenda estabelecimentos que nao possuem as caracteristicas passadas como parametro
     * @param tipoEstabelecimento
     * (bar- cantina- restaurante) o tipo que sera desconsiderado na recomendacao
     * @param tipoAlmoco
     * (self-service, prato-feito, a la carte) o tipo que sera desconsiderado na recomendacao
     * @param tipoAlmoco
     * o local que sera desconsiderado na recomendacao
     * @return
     * a lista com os estabelecimentos filtrados por tipo, forma de almoco e local
     */
    public static List<Estabelecimento> filtraEstabelecimentos(String tipoEstabelecimento, String tipoAlmoco, String localizacao){
    
    	if (tipoEstabelecimento == null){
    		tipoEstabelecimento = "TIPO-DEFAULT";
    	}
    	if (tipoAlmoco == null){
    		tipoAlmoco = "TIPO-DEFAULT";
    	}
    	if (localizacao == null){
    		localizacao = "LOCALIZACAO-DEFAULT";
    	}
    	
    	List<Estabelecimento> ranking = getRankingGeral();
    	List<Estabelecimento> saidaFiltrada = new ArrayList<Estabelecimento>();
    	
    	for (Estabelecimento e : ranking){
    		if (!e.getNome().toLowerCase().contains(tipoEstabelecimento.toLowerCase()) 
    				&& (!e.getEndereco().toLowerCase().contains(localizacao.toLowerCase()))
    				&& (!e.getTipoAlmoco().getNovaCategoria().toLowerCase().contains(tipoAlmoco.toLowerCase()))){
    			saidaFiltrada.add(e);
    		}
    	}
    	return saidaFiltrada;
    }

}
    
    
